// ========== Copyright Header Begin ==========================================
// 
// OpenSPARC T1 Processor File: Blaze_Ni_Access.cc
// Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES.
// 
// The above named program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public
// License version 2 as published by the Free Software Foundation.
// 
// The above named program is distributed in the hope that it will be 
// useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// General Public License for more details.
// 
// You should have received a copy of the GNU General Public
// License along with this work; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
// 
// ========== Copyright Header End ============================================

// 
//  blaze-glue-access-Ni.cc
//  -------------
//
//  "glue" code which makes BLAZE cpu module from RS
//   12/15/2003
//

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <errno.h>
#include <sys/syscall.h>
#include <sys/types.h>	
#include <sys/time.h>	      
#include <unistd.h>	
#include <inttypes.h>
#include <stdarg.h>

#include <thread.h>

// BLAZE stuff
#include "Ni/Blaze_Headers.h"

///////////////////////////////////////////////////// 
#include "Ni/Blaze_Glue_Cpu.h"

/////////////////////////////////////////////////////

#include "Ni/Ni_System.h"
#include "Ni/Ni_Cpu.h"
#include "Ni/Ni_Core.h"

/////////////////////////////////////////////////////

using namespace Riesling;

/////////////////////////////////////////////////////

typedef uint64_t  (* access_fn) (void*);
typedef uint64_t  (* access_vec_fn) (void*, int);

#define GLUE_Ni_ITLB 2233
#define GLUE_Ni_DTLB 2233

#define NI_TLB_SIZE  64
#define MAX_CPU      64

class GLUE_mmu 
{

    public:

    uint32_t type;
    void *glue_ni_mmu;
    void *glue_ni_tlb;
};

// REG ALLOCATOR : 0-15 CPUID 16 -XXX regnum

/////////////////////////////////////////////////////

class GLUE_RegAccessT
{

   public:

    const char    * name;
    uint32_t        type;
    access_fn       get_action;
    access_vec_fn   get_action_vec;
    void          * rhandle [MAX_CPU];
}; 

/////////////////////////////////////////////////////

static uint64_t acc_g0  (void*);
static uint64_t acc_g1  (void*);
static uint64_t acc_g2  (void*);
static uint64_t acc_g3  (void*);
static uint64_t acc_g4  (void*);
static uint64_t acc_g5  (void*);
static uint64_t acc_g6  (void*);
static uint64_t acc_g7  (void*);

static uint64_t acc_o0  (void*);
static uint64_t acc_o1  (void*);
static uint64_t acc_o2  (void*);
static uint64_t acc_o3  (void*);
static uint64_t acc_o4  (void*);
static uint64_t acc_o5  (void*);
static uint64_t acc_o6  (void*);
static uint64_t acc_o7  (void*);

static uint64_t acc_l0  (void*);
static uint64_t acc_l1  (void*);
static uint64_t acc_l2  (void*);
static uint64_t acc_l3  (void*);
static uint64_t acc_l4  (void*);
static uint64_t acc_l5  (void*);
static uint64_t acc_l6  (void*);
static uint64_t acc_l7  (void*);

static uint64_t acc_pc  (void*);
static uint64_t acc_npc (void*);
static uint64_t acc_ccr (void*);
static uint64_t acc_pstate (void*);
static uint64_t acc_asi (void*);
static uint64_t acc_tt_vec  (void*, int idx);
static uint64_t acc_rf_vec  (void*, int idx);
static uint64_t acc_tl (void*);

/////////////////////////////////////////////////////

#define SPEC_REG 7654
#define GP_REG   2345 

static GLUE_RegAccessT reg_access [] = 

{

  {"g0",  GP_REG, acc_g0, acc_rf_vec},  {"g1", GP_REG, acc_g1, NULL},
  {"g2",  GP_REG, acc_g2, NULL},  {"g3", GP_REG, acc_g2, NULL},
  {"g4",  GP_REG, acc_g4, NULL},  {"g5", GP_REG, acc_g3, NULL},
  {"g6",  GP_REG, acc_g6, NULL},  {"g7", GP_REG, acc_g4, NULL},

  {"o0",  GP_REG, acc_o0, NULL},  {"o1", GP_REG, acc_o1, NULL},
  {"o2",  GP_REG, acc_o2, NULL},  {"o3", GP_REG, acc_o3, NULL},
  {"o4",  GP_REG, acc_o4, NULL},  {"o5", GP_REG, acc_o5, NULL},
  {"o6",  GP_REG, acc_o6, NULL},  {"o7", GP_REG, acc_o7, NULL},

  {"l0",  GP_REG, acc_l0, NULL},  {"l1", GP_REG, acc_l1, NULL},
  {"l2",  GP_REG, acc_l2, NULL},  {"l3", GP_REG, acc_l3, NULL},
  {"l4",  GP_REG, acc_l4, NULL},  {"l5", GP_REG, acc_l5, NULL},
  {"l6",  GP_REG, acc_l6, NULL},  {"l7", GP_REG, acc_l7, NULL},


  {"pc",     SPEC_REG, acc_pc, NULL}, {"npc", SPEC_REG, acc_npc, NULL},
  {"pstate", SPEC_REG, acc_pstate, NULL},
  {"ccr",    SPEC_REG, acc_ccr, NULL},

  {"asi",    SPEC_REG, acc_asi, NULL},
  {"tt",     SPEC_REG, NULL, acc_tt_vec},
  {"tl",     SPEC_REG, acc_tl, NULL},
};

/////////////////////////////////////////////////////

uint64_t acc_rf_vec (void * p, int idx)
{
    RegisterFile * rf = (RegisterFile *)p;
    return rf->get (idx);
}

/////////////////////////////////////////////////////

static uint64_t acc_g0 (void * p)
{
    RegisterFile * rf = (RegisterFile *)p;
    return rf->get (0);
}

static uint64_t acc_g1 (void * p)
{
    RegisterFile * rf = (RegisterFile *)p;
    return rf->get (1);
}

static uint64_t acc_g2 (void * p)
{
    RegisterFile * rf = (RegisterFile *)p;
    return rf->get (2);
}

static uint64_t acc_g3 (void * p)
{
    RegisterFile * rf = (RegisterFile *)p;
    return rf->get (3);
}

static uint64_t acc_g4 (void * p)
{
    RegisterFile * rf = (RegisterFile *)p;
    return rf->get (4);
}

static uint64_t acc_g5 (void * p)
{
    RegisterFile * rf = (RegisterFile *)p;
    return rf->get (5);
}

static uint64_t acc_g6 (void * p)
{
    RegisterFile * rf = (RegisterFile *)p;
    return rf->get (6);
}

static uint64_t acc_g7 (void * p)
{
    RegisterFile * rf = (RegisterFile *)p;
    return rf->get (7);
}

////////////////////////////////////////

static uint64_t acc_o0 (void * p)
{
    RegisterFile * rf = (RegisterFile *)p;
    return rf->get (8);
}

static uint64_t acc_o1 (void * p)
{
    RegisterFile * rf = (RegisterFile *)p;
    return rf->get (9);
}

static uint64_t acc_o2 (void * p)
{
    RegisterFile * rf = (RegisterFile *)p;
    return rf->get (10);
}

static uint64_t acc_o3 (void * p)
{
    RegisterFile * rf = (RegisterFile *)p;
    return rf->get (11);
}

static uint64_t acc_o4 (void * p)
{
    RegisterFile * rf = (RegisterFile *)p;
    return rf->get (12);
}

static uint64_t acc_o5 (void * p)
{
    RegisterFile * rf = (RegisterFile *)p;
    return rf->get (13);
}

static uint64_t acc_o6 (void * p)
{
    RegisterFile * rf = (RegisterFile *)p;
    return rf->get (14);
}

static uint64_t acc_o7 (void * p)
{
    RegisterFile * rf = (RegisterFile *)p;
    return rf->get (15);
}

/////////////////////////////////////////////////////

static uint64_t acc_l0 (void * p)
{
    RegisterFile * rf = (RegisterFile *)p;
    return rf->get (16);
}

static uint64_t acc_l1 (void * p)
{
    RegisterFile * rf = (RegisterFile *)p;
    return rf->get (17);
}

static uint64_t acc_l2 (void * p)
{
    RegisterFile * rf = (RegisterFile *)p;
    return rf->get (18);
}

static uint64_t acc_l3 (void * p)
{
    RegisterFile * rf = (RegisterFile *)p;
    return rf->get (19);
}

static uint64_t acc_l4 (void * p)
{
    RegisterFile * rf = (RegisterFile *)p;
    return rf->get (20);
}

static uint64_t acc_l5 (void * p)
{
    RegisterFile * rf = (RegisterFile *)p;
    return rf->get (21);
}

static uint64_t acc_l6 (void * p)
{
    RegisterFile * rf = (RegisterFile *)p;
    return rf->get (22);
}

static uint64_t acc_l7 (void * p)
{
    RegisterFile * rf = (RegisterFile *)p;
    return rf->get (23);
}

/////////////////////////////////////////////////////

static uint64_t acc_pc (void * p)
{
    Ni_ArchState * ps = (Ni_ArchState *)p;
    return ps->getPc();
}

/////////////////////////////////////////////////////

static uint64_t acc_npc (void * p)
{
    Ni_ArchState * ps = (Ni_ArchState *)p;
    return ps->getNpc();
}

/////////////////////////////////////////////////////

static uint64_t acc_pstate (void * p)
{
    Ni_ArchState * ps = (Ni_ArchState *)p;
    uint64_t pstate_v;
    pstate_v = ps->getPstateRegPtr()->getNative();
    return pstate_v;
}

/////////////////////////////////////////////////////

static uint64_t acc_ccr (void * p)
{
    Ni_ArchState * ps = (Ni_ArchState *)p;
    return ps->getCcrRegPtr()->getNative();
}

/////////////////////////////////////////////////////

uint64_t acc_asi (void * p)
{
    Ni_ArchState * ps = (Ni_ArchState *)p;
    return ps->getAsiRegPtr()->getNative();
}

/////////////////////////////////////////////////////

uint64_t acc_tl (void * p)
{
    Ni_ArchState * ps = (Ni_ArchState *)p;
    return ps->getTrapLevelRegPtr()->getNative();
}

/////////////////////////////////////////////////////

uint64_t acc_tt_vec (void * p, int idx)
{
    Ni_ArchState * ps = (Ni_ArchState *)p;
    return ps->getTrapTypeRegPtr()->getTrapType(idx);
}

/////////////////////////////////////////////////////

uint64_t   CPU_getreg_by_handle_64_ni (RHANDLE64 handle)
{

    uint64_t rlocator     = (uint64_t) handle;
    uint32_t rindx        = rlocator >> 16;
    uint32_t cpuid        = rlocator & 0xffff;
    GLUE_RegAccessT  * pe = &reg_access[rindx];

    if (pe->get_action) 
        return pe->get_action(pe->rhandle[cpuid]);
    else {
        fprintf (stderr, "GLUE: reg <%s> - no accessor!\n", pe->name);
        return 0;
    }
}

/////////////////////////////////////////////////////

uint64_t   CPU_getreg_by_handle_vec_64_ni (RHANDLE64 handle, int idx)
{
    uint64_t rlocator = (uint64_t) handle;
    uint32_t rindx    = rlocator >> 16;
    uint32_t cpuid    = rlocator & 0xffff;
    GLUE_RegAccessT * pe = &reg_access[rindx];


    if (pe->get_action_vec) 
        return pe->get_action_vec (pe->rhandle[cpuid], idx);
    else {
        fprintf (stderr, "GLUE: reg <%s> - no accessor!\n", pe->name);
        return 0;
    }

}

/////////////////////////////////////////////////////

uint32_t   CPU_getreg_by_handle_32_ni (RHANDLE32 handle)
{

    uint64_t rlocator = (uint64_t) handle;
    uint32_t rindx    = rlocator >> 16;
    uint32_t cpuid    = rlocator & 0xffff;
    GLUE_RegAccessT * pe = &reg_access[rindx];

    if (pe->get_action) 
        return (uint32_t) pe->get_action(pe->rhandle[cpuid]);
    else {
        fprintf (stderr, "GLUE: reg <%s> - no accessor!\n", pe->name);
        return 0;
    }
}

/////////////////////////////////////////////////////

uint32_t   CPU_getreg_by_handle_vec_32_ni (RHANDLE32 handle, int idx)
{
    uint64_t rlocator = (uint64_t) handle;
    uint32_t rindx    = rlocator >> 16;
    uint32_t cpuid    = rlocator & 0xffff;
    GLUE_RegAccessT * pe = &reg_access[rindx];

    if (pe->get_action_vec) 
        return (uint32_t) pe->get_action_vec(pe->rhandle[cpuid], idx);
    else {
        fprintf (stderr, "GLUE: reg <%s> - no accessor!\n", pe->name);
        return 0;
    }
}

/////////////////////////////////////////////////////

uint16_t   CPU_getreg_by_handle_16_ni (RHANDLE16 handle)
{

    uint64_t rlocator = (uint64_t) handle;
    uint32_t rindx    = rlocator >> 16;
    uint32_t cpuid    = rlocator & 0xffff;
    GLUE_RegAccessT * pe = &reg_access[rindx];


    if (pe->get_action) 
        return (uint16_t) pe->get_action(pe->rhandle[cpuid]);
    else {
        fprintf (stderr, "GLUE: reg <%s> - no accessor!\n", pe->name);
        return 0;
    }
}

/////////////////////////////////////////////////////

uint8_t   CPU_getreg_by_handle_8_ni (RHANDLE8 handle)
{
    uint64_t rlocator = (uint64_t) handle;
    uint32_t rindx    = rlocator >> 16;
    uint32_t cpuid    = rlocator & 0xffff;
    GLUE_RegAccessT * pe = &reg_access[rindx];

    if (pe->get_action) 
        return (uint8_t) pe->get_action(pe->rhandle[cpuid]);
    else {
        fprintf (stderr, "GLUE: reg <%s> - no accessor!\n", pe->name);
        return 0;
    }
}

/////////////////////////////////////////////////////

RHANDLE64  CPU_access_rhandle_64_ni   (cpuT *sp, char *regname)
{
        int                  indx;
	Ni_Strand  *ni_strand = (Ni_Strand*)sp->prscpu;
	uint32_t             rlocator = 0;

        for (indx = 0; indx < sizeof(reg_access)/sizeof(GLUE_RegAccessT); indx++) {
	    GLUE_RegAccessT *last = &reg_access[indx];

	    if (strcmp(last->name, regname) == NULL) {
	        rlocator = (indx << 16) | sp->cpuid;
	        if (last->type == GP_REG) {
		    Ni_ArchState * ni_state  = (Ni_ArchState*)ni_strand->getArchStatePtr();
		    RegisterFile * rf        = ni_state->getRegisterFilePtr();
                    last->rhandle[sp->cpuid] = rf;
		    return (RHANDLE64)rlocator;
                } 
		else {
		    Ni_ArchState * ni_state  = (Ni_ArchState*)ni_strand->getArchStatePtr();
                    last->rhandle[sp->cpuid] = ni_state;
		    return (RHANDLE64)rlocator;
                }
            }
	}
	fprintf (stderr, "GLUE: Unknown register <%s>\n", regname);
	return NULL;
}

/////////////////////////////////////////////////////

RHANDLE32  CPU_access_rhandle_32_ni   (cpuT *sp, char *regname)
{
        int                  indx;
	Ni_Strand  *ni_strand = (Ni_Strand*)sp->prscpu;
	uint32_t             rlocator = 0;

        for (indx = 0; indx < sizeof(reg_access)/sizeof(GLUE_RegAccessT); indx++) {
	    GLUE_RegAccessT *last = &reg_access[indx];

	    if (strcmp(last->name, regname) == NULL) {
	        rlocator = (indx << 16) | sp->cpuid;
	        if (last->type == GP_REG) {
		    Ni_ArchState * ni_state  = (Ni_ArchState*)ni_strand->getArchStatePtr();
		    RegisterFile * rf        = ni_state->getRegisterFilePtr();
                    last->rhandle[sp->cpuid] = rf;
		    return (RHANDLE32)rlocator;
                } 
		else {
		    Ni_ArchState * ni_state  = (Ni_ArchState*)ni_strand->getArchStatePtr();

                    last->rhandle[sp->cpuid] = ni_state;
		    return (RHANDLE32)rlocator;
                }
            }
	}
	fprintf (stderr, "GLUE: Unknown register <%s>\n", regname);
	return NULL;
}

/////////////////////////////////////////////////////

RHANDLE16  CPU_access_rhandle_16_ni   (cpuT *sp, char *regname)
{
        int                  indx;
	Ni_Strand  *ni_strand = (Ni_Strand*)sp->prscpu;
	uint32_t             rlocator = 0;

        for (indx = 0; indx < sizeof(reg_access)/sizeof(GLUE_RegAccessT); indx++) {
	    GLUE_RegAccessT *last = &reg_access[indx];

	    if (strcmp(last->name, regname) == NULL) {
	        rlocator = (indx << 16) | sp->cpuid;
	        if (last->type == GP_REG) {
		    Ni_ArchState * ni_state  = (Ni_ArchState*)ni_strand->getArchStatePtr();
		    RegisterFile * rf        = ni_state->getRegisterFilePtr();
                    last->rhandle[sp->cpuid] = rf;
		    return (RHANDLE16)rlocator;
                } 
		else {
		    Ni_ArchState * ni_state  = (Ni_ArchState*)ni_strand->getArchStatePtr();
                    last->rhandle[sp->cpuid] = ni_state;
		    return (RHANDLE16)rlocator;
                }
            }
	}
	fprintf (stderr, "GLUE: Unknown register <%s>\n", regname);
	return NULL;
}

/////////////////////////////////////////////////////

RHANDLE8  CPU_access_rhandle_8_ni   (cpuT *sp, char *regname)
{
        int                  indx;
	Ni_Strand  *ni_strand = (Ni_Strand*)sp->prscpu;
	uint32_t             rlocator = 0;

        for (indx = 0; indx < sizeof(reg_access)/sizeof(GLUE_RegAccessT); indx++) {
	    GLUE_RegAccessT *last = &reg_access[indx];

	    if (strcmp(last->name, regname) == NULL) {
	        rlocator = (indx << 16) | sp->cpuid;
	        if (last->type == GP_REG) {
		    Ni_ArchState * ni_state  = (Ni_ArchState*)ni_strand->getArchStatePtr();
		    RegisterFile * rf        = ni_state->getRegisterFilePtr();
                    last->rhandle[sp->cpuid] = rf;
		    return (RHANDLE8)rlocator;
                } 
		else {
		    Ni_ArchState * ni_state  = (Ni_ArchState*)ni_strand->getArchStatePtr();
                    last->rhandle[sp->cpuid] = ni_state;
		    return (RHANDLE8)rlocator;
                }
            }
	}
	fprintf (stderr, "GLUE: Unknown register <%s>\n", regname);
	return NULL;
}

/////////////////////////////////////////////////////

RHANDLEP  CPU_access_rhandle_P_ni   (cpuT *sp, char *regname)
{

	Ni_Strand  *ni_strand = (Ni_Strand*)sp->prscpu;
        Ni_Mmu	    *pmmu = ni_strand->getMmuPtr();

        GLUE_mmu *pglue_mmu = new GLUE_mmu ();
        pglue_mmu->glue_ni_mmu = (void*)pmmu;

        if (strcmp(regname, "immu") == NULL) {
	    pglue_mmu->type = GLUE_Ni_ITLB;
	    pglue_mmu->glue_ni_tlb = pmmu->get_itlb();
	    return (RHANDLEP)pglue_mmu;
        }
        else if (strcmp(regname, "dmmu") == NULL) {
	    pglue_mmu->type = GLUE_Ni_DTLB;
	    pglue_mmu->glue_ni_tlb = pmmu->get_dtlb();
	    return (RHANDLEP)pglue_mmu;
	}

	fprintf (stderr, "GLUE: Unknown feature <%s>\n", regname);
	return NULL;
}

/////////////////////////////////////////////////////

uint64_t  MMU_get_mmu_reg_by_name_ni (mmuT* sp, char *regname)
{
        GLUE_mmu *pglue_mmu = (GLUE_mmu*)sp;
        if (strcmp (regname, "pcontext") == NULL) {
 	    Ni_Mmu      *pmmu = (Ni_Mmu*)pglue_mmu->glue_ni_mmu;
	    Ni_MmuState *pmmu_state = pmmu->getMmuStatePtr();
	    //            Mmu::Sf_ContextReg     pctxt = pmmu->primary_context[0];  // There is [1] as well
            return pmmu_state->getPrimaryDContext();// pctxt.getNative ();
	}
	else if (strcmp (regname, "scontext") == NULL) {
 	    Ni_Mmu      *pmmu = (Ni_Mmu*)pglue_mmu->glue_ni_mmu;
	    Ni_MmuState *pmmu_state = pmmu->getMmuStatePtr();
            //Mmu::Sf_ContextReg     pctxt = pmmu->secondary_context[0];  // There is [1] as well
            //return pctxt.getNative ();
            return pmmu_state->getSecondaryContext();// pctxt.getNative ();
        }
        else {
	    fprintf (stderr, "MMU: reg access error - uknown register <%s> \n", regname);
	    return 0;
      }
}

/////////////////////////////////////////////////////

uint32_t       CPU_get_tlb_unitcount_ni   (mmuT *mmu)
{
          return 1;
}

/////////////////////////////////////////////////////

Byte     CPU_get_tlb_type_ni          (mmuT* sp)
{
        GLUE_mmu *pglue_mmu = (GLUE_mmu*)sp;
        if (pglue_mmu->type == GLUE_Ni_ITLB) {
	    return 'I';
        }
        else         if (pglue_mmu->type == GLUE_Ni_DTLB) {
	    return 'D';
        }
	else return 'U';
}

/////////////////////////////////////////////////////

uint32_t  CPU_get_tlb_unitnumlines_ni  (mmuT *pmmu, int unitId)
{
        return NI_TLB_SIZE;
}

/////////////////////////////////////////////////////

uint64_t  CPU_get_tlb_entry_ni   (mmuT *sp, int unitId, int entry, bool_t tag)
{

        uint64_t d;
        GLUE_mmu         *pglue_mmu = (GLUE_mmu*)sp;
        Ni_Mmu      *pmmu = (Ni_Mmu*)pglue_mmu->glue_ni_mmu;
        Tlb      *ptlb =  (pglue_mmu->type == GLUE_Ni_ITLB) ? 
 	                          pmmu->get_itlb()                  :
                                  pmmu->get_dtlb();

        TtePos       ttepos = ptlb->get(entry );
	Tte          *tte   = ttepos.tte_;
        if (tag) {
	    tte->getNativeTag((uint8_t*) &d, 8);
        }
	else {
	    tte->getNativeData((uint8_t*) &d, 8);
        }
        return d;

}

/////////////////////////////////////////////////////

uint32_t  CPU_get_current_context_ni   (cpuT *sp, bool_t dctxt)
{
        Ni_Strand            *ni_strand = (Ni_Strand*)sp->prscpu;
        InstructionEmulator  *ie        = ni_strand->getInstructionEmulator();
        uint32_t                       tl    = ie->get_TL();

        if (tl > 0) {
	    return 0;
        }
        else {
	    Ni_Mmu	 *pmmu = ni_strand->getMmuPtr();
	    Ni_MmuState *pmmu_state = pmmu->getMmuStatePtr();
            //Mmu::Sf_ContextReg     pctxt = pmmu->secondary_context[0];  // There is [1] as well
            //return pctxt.getNative ();
            return pmmu_state->getSecondaryContext();// pctxt.getNative ();

            //Mmu::Sf_ContextReg     pctxt = pmmu->primary_context[0];  
            //return pctxt.getNative ();
        }
}

/////////////////////////////////////////////////////

bool_t  CPU_get_flag_ni  (cpuT *sp,  cpuFlags flags)
{
      Ni_Strand            *ni_strand = (Ni_Strand*)sp->prscpu;
      InstructionEmulator  *ie        = ni_strand->getInstructionEmulator();
      Ni_ArchState          *ni_state  = (Ni_ArchState*)ni_strand->getArchStatePtr();

      switch (flags) {
      case  CPUF_CTI_EXECUTED :
	return ie->get_ctiExecuted();        
      case  CPUF_CTI_TAKEN :
        return ie->get_ctiTaken();
      case  CPUF_PRIV :
	return ni_state->getPstateRegPtr()->getPRIV();
      }
      fprintf (stderr, "CPU:getfag: unknown flag = %d \n", flags);
      return FALSE;
}

/////////////////////////////////////////////////////

extern cpuT *GLUE_get_cpu (int id);

/////////////////////////////////////////////////////

static void ni_print_gp_regs (int tid);

int ni_regs_cmd_action (void * dd, int argc, char ** argv)
{
        int  tid;
	cpuT *sp;

        if (argc <= 2) {
	    fprintf (stderr, "Usage: r <tid> [<RNAME>] \n");
	    return 0;
        }

	sscanf (argv[1], "%i", &tid);

        if (argc == 2) {
	    ni_print_gp_regs (tid);
            return 0;
        }
        sp = GLUE_get_cpu (tid);

        if (strcmp ("pc", argv[2]) == NULL ) {
	    Ni_Strand    *ni_strand = (Ni_Strand*)sp->prscpu;
	    Ni_ArchState *ni_state  = (Ni_ArchState*)ni_strand->getArchStatePtr();
            printf ("0x%llx \n", ni_state->getPc());
        }
	else {
	    fprintf (stderr, "Unknown register: <%s> \n", argv[2]);
        }
	return 0;
}

/////////////////////////////////////////////////////

static void ni_print_gp_regs (int tid) 
{

      //  %g0 0xTTTTTTTTTTTTTTTT 0xTTTTTTTTTTTTTTTT   
      //  %g2  

      cpuT    * sp;
      uint64_t regv[32];
      int      ii;

      if ((tid < 0) ||  (tid >= SYSTEM_get_ncpu())) {
	  fprintf (stderr, "UI: wrong THREAD ID \n");
	  return;
      }
      sp = GLUE_get_cpu (tid);

      Ni_Strand    *ni_strand = (Ni_Strand*)sp->prscpu;
      Ni_ArchState *ni_state  = (Ni_ArchState*)ni_strand->getArchStatePtr();
      RegisterFile *rf        = ni_state->getRegisterFilePtr();

      for (ii = 0; ii < 32; ii++) {
	  regv[ii] = rf->get (ii);
      }

}

/////////////////////////////////////////////////////

